This invention relates to the field of computer communications. More particularly, a system and methods are provided for performing data communications through a protocol stack without incurring the overhead normally imposed by the Streams framework.
The Streams framework, or subsystem, provides a flexible programming model for communication services within computer systems executing a Unix-based operating system. The Streams subsystem defines standard interfaces within kernel space, to provide a modular approach to implementation of a network protocol stack. Within the Streams framework, each protocol layer's module normally communicates through the framework, which provides system calls, kernel resources (e.g., queues) and kernel routines for transferring messages along communication streams built upon the protocol stack.
For each communication stream, the basic Streams model provides a downstream queue for outgoing messages and an upstream queue for incoming messages. Messages are passed up and down the stream, traversing modules which provide the protocol functionality. Transferring a message or communication from one module to the next involves two functions, “canputnext” and “putnext.” The canputnext function determines whether Streams resources (e.g., the queues) can accommodate the message, while the putnext function takes the message and passes it from one module to the next within the stream. When passed from one module to another, a message leaves the first module and enters the Streams framework then the streams framework calls the next module to pass the message on.
It is possible to add and remove modules from a stream at any time during operation of the stream. The ability to add and remove modules requires that the stream be stopped so that the reconfiguration can be effected with no impact to the communications already queued on the stream.
The Streams framework allows queues to build up between modules if the modules have perimeters defined. The perimeters ensure that once in the perimeter, whether it is an outer or inner perimeter for the module, mutual exclusive access to the driver/module-specific data structures is protected by the perimeter.
While perimeters generalize the locking and queuing required to implement a protocol stack, they can cause unnecessary processing overhead when a streams module is implemented with maximum multi-threading capability. In particular, while the Streams framework allows completely multi-threaded modules, it still requires a stream be locked via canputnext and putnext functions.
While executing these functions, the Streams framework employs mutual exclusion (i.e., mutex) locks to control access to a communication stream's queues and to ensure that the stream is not changed (e.g., to add or remove a module) while it is active. Thus, the Streams framework locks the communication stream, accepts the communication (e.g., queues it) and then unlocks the stream. This procedure must be followed for every communication transfer from one module to another.
The continual locking and unlocking of Streams resources causes a noticeable degradation in communication performance. Even though the addition/removal of modules to/from a communication stream may be relatively rare events, the Streams framework imposes a penalty on stream communications in order to accommodate such changes.
One attempted method for avoiding the Streams framework overhead described above involves merging adjacent protocol modules. However, this can be quite difficult, in order to address complexities of both modules. Also, merger of just two modules may not be enough. For example, when attempting to improve the efficiency of passing messages between TCP and IP, UDP (User Datagram Protocol) may also need to be merged since IP underlies both TCP and UDP.
When modules are merged, the resulting protocol stack becomes much less flexible. For example, a third-party module that could normally be inserted between the modules (e.g., a firewall module inserted between IP and a device driver module) cannot easily be added to the modules after they are merged. In addition, it may require substantial time and effort to combine the modules and test the result to ensure all ramifications of the merger are understood and addressed.
Therefore, there is a need for a system and method for passing data communications between protocol layer modules within a communication stream, without incurring the Streams framework overhead normally associated with such activity, and without merging the modules.